#include <typeinfo>
#include <algorithm>
#include <assert.h>
#include <iostream>
/// @brief 通用类为了兼容各种协议
class Any
{
private:
    class Holder
    {
    public:
        virtual ~Holder() {}
        /// @brief 运行时获取类型
        /// @return
        virtual const std::type_info &Type() = 0;
        /// @brief 纯虚函数子类必须实现
        /// @return
        virtual Holder *Clone() = 0;
    };
    template <class T>
    class PlaceHolder : public Holder
    {
    public:
        virtual ~PlaceHolder()
        {
        }
        PlaceHolder(const T &val) : _val(val)
        {
        }
        virtual const std::type_info &Type()
        {
            return typeid(T);
        }
        virtual Holder *Clone()
        {
            return new PlaceHolder<T>(_val);
        }

    public:
        T _val;
    };

    Holder *_content;

public:
    void Swap(Any &other)
    {
        std::swap(other._content, _content);
    }
    template <class T>
    T *Get()
    {
        assert(typeid(T) == _content->Type());
        return &((PlaceHolder<T> *)_content)->_val;
    }
    Any() : _content(nullptr)
    {
    }
    Any(const Any &other)
    {
        if (other._content != nullptr)
            _content = other._content->Clone();
        else
            _content = nullptr;
    }
    template <class T>
    Any(const T &val) : _content(new PlaceHolder<T>(val))
    {
    }

    ~Any()
    {
        delete _content;
    }
    template <class T>
    Any &operator=(const T &val)
    {

        Any(val).Swap(*this);
        return *this;
    }
    Any &operator=(const Any &other)
    {
        Any(other).Swap(*this);
        return *this;
    }
};

// class t
// {
// public:
//     t()
//     {
//         std::cout << "构造" << std::endl;
//     }
//     t(const t &v)
//     {
//         std::cout << "拷贝" << std::endl;
//     }
//     ~t()
//     {
//         std::cout << "析构" << std::endl;
//     }

//     int x = 3;
// };

// int main()
// {
//     Any x;
//     {
//         t tt;
//         x = tt;
//     }
//     x = 10;

//     while (1)
//     {
//     }

//     return 0;
// }